using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;
using System.Net;


namespace Balloon
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Balloon : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager _graphics;
        SpriteBatch _spriteBatch;
        GameState _state;
        MapClient _mapClient;
        Acl _acl;

        SpriteFont _font;
        Texture2D _mapImage;
        Texture2D _small_balloon;
        Texture2D _fire;
        Texture2D _ice;
        Texture2D _play;
        Texture2D _pause;
        Texture2D _music_i;
        Texture2D _origin;
        Vector2 _center;
        Vector2 _fire_p;
        Vector2 _ice_p;
        Vector2 _music_p;
        Vector2 _origin_p;
        Song _song1;
        Song _song2;
        Song _playing;

        Rectangle _fire_r;
        Rectangle _ice_r;
        Rectangle _music_r;
        Rectangle _origin_r;

        public Balloon()
        {
            _graphics = new GraphicsDeviceManager(this);
            _graphics.IsFullScreen = true;
            _graphics.SupportedOrientations = DisplayOrientation.LandscapeLeft;
            Content.RootDirectory = "Content";

            _mapClient = new MapClient();
            _mapClient.MapLoaded += new MapLoadedEventHandler(map_loaded);

            _acl = new Acl();
            _acl.AclRead += new AclReadEventHandler(_mapClient.on_acl_read);

            TouchPanel.EnabledGestures = GestureType.Tap;

            MediaPlayer.MediaStateChanged += (sender, e)=>
                {
                    if (MediaPlayer.State == MediaState.Stopped)
                    {
                        if (_playing == _song1)
                            _playing = _song2;
                        else
                            _playing = _song1;
                        MediaPlayer.Play(_playing);
                    }
                    else if (MediaPlayer.State == MediaState.Paused)
                    {
                        _music_i = _pause;
                    }
                    else if (MediaPlayer.State == MediaState.Playing)
                    {
                        _music_i = _play;
                    }
                };


            // Frame rate is 30 fps by default for Windows Phone.
            TargetElapsedTime = TimeSpan.FromTicks(333333);

            // Extend battery life under lock.
            InactiveSleepTime = TimeSpan.FromSeconds(1);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            _state = GameState.Initialize;
            _mapClient.Initialize();
            _acl.Initialize();
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            _font = Content.Load<SpriteFont>("Font");
            _mapImage = Content.Load<Texture2D>("balloon");
            _small_balloon = Content.Load<Texture2D>("small_balloon");
            _fire = Content.Load<Texture2D>("fire");
            _ice = Content.Load<Texture2D>("ice");
            
            _play = Content.Load<Texture2D>("play");
            _pause = Content.Load<Texture2D>("pause");
            // set current music icon
            _music_i = _play;
            _song1 = this.Content.Load<Song>("sound\\load");
            _song2 = this.Content.Load<Song>("sound\\play");
            _playing = _song1;
            MediaPlayer.Play(_playing);

            _origin = Content.Load<Texture2D>("origin");

            _center = new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
            _fire_p = new Vector2(GraphicsDevice.Viewport.Width - 100, GraphicsDevice.Viewport.Height - 400);
            _ice_p = new Vector2(GraphicsDevice.Viewport.Width - 100, GraphicsDevice.Viewport.Height - 300);
            _music_p = new Vector2(GraphicsDevice.Viewport.Width - 80, GraphicsDevice.Viewport.Height - 200);
            _origin_p = new Vector2(GraphicsDevice.Viewport.Width - 100, GraphicsDevice.Viewport.Height - 100);

            _fire_r = new Rectangle((int)_fire_p.X, (int)_fire_p.Y, _fire.Width, _fire.Height);
            _ice_r = new Rectangle((int)_ice_p.X, (int)_ice_p.Y, _ice.Width, _ice.Height);
            _music_r = new Rectangle((int)_music_p.X, (int)_music_p.Y, _play.Width, _play.Height);
            _origin_r = new Rectangle((int)_origin_p.X, (int)_origin_p.Y, _origin.Width, _origin.Height);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            while (TouchPanel.IsGestureAvailable && _state == GameState.Playing)
            {
                GestureSample sample = TouchPanel.ReadGesture();
                if (is_fire(sample.Position))
                {
                    _mapClient.fire();
                }
                else if (is_ice(sample.Position))
                {
                    _mapClient.ice();
                }
                else if (is_music(sample.Position))
                {
                    _toggle_music();
                }
                else if (is_origin(sample.Position))
                {
                    _mapClient.Initialize();
                }
            }

            base.Update(gameTime);
        }

        private void _toggle_music()
        {
            if (MediaPlayer.State == MediaState.Playing)
            {
                MediaPlayer.Pause();
            }
            else if (MediaPlayer.State == MediaState.Paused)
            {
                MediaPlayer.Resume();
            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here
            _spriteBatch.Begin();

            _spriteBatch.Draw(_mapImage, Vector2.Zero, Color.White);
            if (_state == GameState.Initialize)
            {
                draw_text("Loading position...");
            }
            else if (_state == GameState.Playing)
            {
                //draw_text(_mapClient._co.Latitude.ToString() + " | " + _mapClient._co.Longitude.ToString());
                //draw_text(_mapClient._scale.ToString());
                _spriteBatch.Draw(_small_balloon, _center, Color.White);
                _spriteBatch.Draw(_fire, _fire_p, Color.White);
                _spriteBatch.Draw(_ice, _ice_p, Color.White);
                _spriteBatch.Draw(_music_i, _music_p, Color.White);
                _spriteBatch.Draw(_origin, _origin_p, Color.White);
            }

            _spriteBatch.End();

            base.Draw(gameTime);
        }

        private void draw_text(string text)
        {
            Color color = Color.White;
            Vector2 size = _font.MeasureString(text);
            Vector2 position = new Vector2(10, GraphicsDevice.Viewport.Height - size.Y - 10);
            _spriteBatch.DrawString(_font, text, position, color);
        }

        private void map_loaded(object sender, OpenReadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                _mapImage = Texture2D.FromStream(_graphics.GraphicsDevice, e.Result);
                if (_state == GameState.Initialize)
                {
                    _state = GameState.Playing;
                    //start accelerometer
                    _acl.Start();
                    //change theme music
                    MediaPlayer.Stop();
                }
            }
        }

        private bool is_fire(Vector2 pos)
        {
            return _sample(pos).Intersects(_fire_r);
        }

        private bool is_ice(Vector2 pos)
        {
            return _sample(pos).Intersects(_ice_r);
        }

        private bool is_music(Vector2 pos)
        {
            return _sample(pos).Intersects(_music_r);
        }

        private bool is_origin(Vector2 pos)
        {
            return _sample(pos).Intersects(_origin_r);
        }

        private Rectangle _sample(Vector2 pos)
        {
            //Prepare a rectangle around touch position to allow more comfortable touch 
            return new Rectangle((int)pos.X - 5, (int)pos.Y - 5, 10, 10);
        }

    }
}
